#    pythonequations is a collection of equations expressed as Python classes
#    Copyright (C) 2008 James R. Phillips
#    2548 Vera Cruz Drive
#    Birmingham, AL 35235 USA
#    email: zunzun@zunzun.com
#
#    License: BSD-style (see LICENSE.txt in main source directory)
#    Version info: $Id: Polynomial.py 274 2010-09-29 13:16:14Z zunzun.com $

import pythonequations, pythonequations.EquationBaseClasses, pythonequations.ExtraCodeForEquationBaseClasses
import numpy
numpy.seterr(all = 'raise') # numpy raises warnings, convert to exceptions to trap them


class Linear3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = True
    RequiresAutoGeneratedInverseForms = True
    _name ="Linear"
    _HTML = "z = a + bx + cy"
    coefficientDesignatorTuple = ("a", "b", "c")
    LinearSSQSolverFlag = 1
    function_cpp_code = 'temp = coeff[0] + coeff[1] * _id[_cwo[1]+i] + coeff[2] * _id[_cwo[2]+i];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])

    def SpecificCodeCPP(self):
        s = "\ttemp += " + self.coefficientDesignatorTuple[0] + ";\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[1] + " * x_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[2] + " * y_in;\n"
        return s



class SimplifiedQuadratic3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = True
    RequiresAutoGeneratedInverseForms = True
    _name ="Simplified Quadratic"
    _HTML = "z = a + bx + cy + dx<SUP>2</SUP> + fy<SUP>2</SUP>"
    coefficientDesignatorTuple = ("a", "b", "c", "d", 'f')
    LinearSSQSolverFlag = 1
    function_cpp_code = 'temp = coeff[0] + coeff[1] * _id[_cwo[1]+i] + coeff[2] * _id[_cwo[2]+i] + coeff[3] * _id[_cwo[3]+i] + coeff[4] * _id[_cwo[4]+i];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowY(NameOrValueFlag=1, args=[2.0]), [2.0]])

    def SpecificCodeCPP(self):
        s = "\ttemp += " + self.coefficientDesignatorTuple[0] + ";\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[1] + " * x_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[2] + " * y_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[3] + " * pow(x_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[4] + " * pow(y_in, 2.0);\n"
        return s



class FullQuadratic3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = True
    RequiresAutoGeneratedInverseForms = True
    _name ="Full Quadratic"
    _HTML = "z = a + bx + cy + dx<SUP>2</SUP> + fy<SUP>2</SUP> + gxy"
    coefficientDesignatorTuple = ("a", "b", "c", "d", "f", "g")
    LinearSSQSolverFlag = 1
    function_cpp_code = 'temp = coeff[0] + coeff[1] * _id[_cwo[1]+i] + coeff[2] * _id[_cwo[2]+i] + coeff[3] * _id[_cwo[3]+i] + coeff[4] * _id[_cwo[4]+i] + coeff[5] * _id[_cwo[5]+i];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowY(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_XY(NameOrValueFlag=1), []])

    def SpecificCodeCPP(self):
        s = "\ttemp += " + self.coefficientDesignatorTuple[0] + ";\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[1] + " * x_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[2] + " * y_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[3] + " * pow(x_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[4] + " * pow(y_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[5] + " * x_in * y_in;\n"
        return s



class SimplifiedCubic3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = True
    RequiresAutoGeneratedInverseForms = True
    _name ="Simplified Cubic"
    _HTML = "z = a + bx + cy + dx<SUP>2</SUP> + fy<SUP>2</SUP> + gx<SUP>3</SUP> + hy<SUP>3</SUP>"
    coefficientDesignatorTuple = ("a", "b", "c", "d", "f", "g", "h")
    LinearSSQSolverFlag = 1
    function_cpp_code = 'temp = coeff[0] + coeff[1] * _id[_cwo[1]+i] + coeff[2] * _id[_cwo[2]+i] + coeff[3] * _id[_cwo[3]+i] + coeff[4] * _id[_cwo[4]+i] + coeff[5] * _id[_cwo[5]+i] + coeff[6] * _id[_cwo[6]+i];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowY(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX(NameOrValueFlag=1, args=[3.0]), [3.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowY(NameOrValueFlag=1, args=[3.0]), [3.0]])

    def SpecificCodeCPP(self):
        s = "\ttemp += " + self.coefficientDesignatorTuple[0] + ";\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[1] + " * x_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[2] + " * y_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[3] + " * pow(x_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[4] + " * pow(y_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[5] + " * pow(x_in, 3.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[6] + " * pow(y_in, 3.0);\n"
        return s



class FullCubic3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = True
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = True
    RequiresAutoGeneratedInverseForms = True
    _name ="Full Cubic"
    _HTML = "z = a + bx + cy + dx<SUP>2</SUP> + fy<SUP>2</SUP> + gx<SUP>3</SUP> + hy<SUP>3</SUP> + ixy + jx<SUP>2</SUP>y + kxy<SUP>2</SUP>"
    coefficientDesignatorTuple = ("a", "b", "c", "d", "f", "g", "h", "i", "j", "k")
    LinearSSQSolverFlag = 1
    function_cpp_code = 'temp = coeff[0] + coeff[1] * _id[_cwo[1]+i] + coeff[2] * _id[_cwo[2]+i] + coeff[3] * _id[_cwo[3]+i] + coeff[4] * _id[_cwo[4]+i] + coeff[5] * _id[_cwo[5]+i] + coeff[6] * _id[_cwo[6]+i] + coeff[7] * _id[_cwo[7]+i] + coeff[8] * _id[_cwo[8]+i] + coeff[9] * _id[_cwo[9]+i];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Ones(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_X(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Y(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowY(NameOrValueFlag=1, args=[2.0]), [2.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX(NameOrValueFlag=1, args=[3.0]), [3.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowY(NameOrValueFlag=1, args=[3.0]), [3.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_XY(NameOrValueFlag=1), []])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX_PowY(NameOrValueFlag=1, args=[2.0, 1.0]), [2.0, 1.0]])
        self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX_PowY(NameOrValueFlag=1, args=[1.0, 2.0]), [1.0, 2.0]])

    def SpecificCodeCPP(self):
        s = "\ttemp += " + self.coefficientDesignatorTuple[0] + ";\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[1] + " * x_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[2] + " * y_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[3] + " * pow(x_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[4] + " * pow(y_in, 2.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[5] + " * pow(x_in, 3.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[6] + " * pow(y_in, 3.0);\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[7] + " * x_in * y_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[8] + " * pow(x_in, 2.0) * y_in;\n"
        s += "\ttemp += " + self.coefficientDesignatorTuple[9] + " * x_in * pow(y_in, 2.0);\n"
        return s



class Polynomial3D(pythonequations.EquationBaseClasses.Equation3D):
    RequiresAutoGeneratedGrowthAndDecayForms = False
    RequiresAutoGeneratedOffsetForm = False
    RequiresAutoGeneratedReciprocalForm = True
    RequiresAutoGeneratedInverseForms = True
    _name ="User-Selectable Polynomial"
    _HTML = "z = a + bx + cy + dx<SUP>2</SUP> + fy<SUP>2</SUP> + gx<SUP>3</SUP> + hy<SUP>3</SUP> + ..."
    coefficientDesignatorTuple = ()
    polynomialFlag = 1
    LinearSSQSolverFlag = 1
    function_cpp_code = 'temp = 0.0;\nfor (int k=0; k<_nc; k++)\n\ttemp += coeff[k] * _id[_cwo[k]+i];'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        for i in range(0, self.xPolynomialOrder+1): # 0 - xOrder
            for j in range(0, self.yPolynomialOrder+1): # 0 - yOrder
                self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_PowX_PowY(NameOrValueFlag=1, args=[float(i), float(j)]), [float(i), float(j)]])

    def SpecificCodeCPP(self):
        s = ""
        for i in range(0, self.xPolynomialOrder+1): # 0 - xOrder
            for j in range(0, self.yPolynomialOrder+1): # 0 - yOrder
                index = (i*(self.yPolynomialOrder+1))+j
                if i == 0 and j == 0:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + ";\n"
                elif i == 1 and j == 0:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * x_in;\n"
                elif i > 1 and j == 0:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * pow(x_in, " + str(i) + ".0);\n"
                elif i > 1 and j == 1:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * pow(x_in, " + str(i) + ".0) * y_in;\n"
                elif i == 0 and j == 1:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * y_in;\n"
                elif i == 0 and j > 1:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * pow(y_in, " + str(j) + ".0);\n"
                elif i == 1 and j > 1:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * x_in * pow(y_in, " + str(j) + ".0);\n"
                elif i == 1 and j == 1:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * x_in * y_in;\n"
                else:
                    s += "\ttemp += " + self.coefficientDesignatorTuple[index] + " * pow(x_in, " + str(i) + ".0) * pow(y_in, " + str(j) + ".0);\n"
        return s


    def Initialize(self):
        self.coefficientDesignatorTuple = ()
        
        self._HTML = "z = "
        indexmax = (self.xPolynomialOrder+1) * (self.yPolynomialOrder+1)
        for i in range(0, self.xPolynomialOrder+1): # 0 - xOrder
            for j in range(0, self.yPolynomialOrder+1): # 0 - yOrder
                index = (i*(self.yPolynomialOrder+1))+j
                self.coefficientDesignatorTuple += (pythonequations.EquationBaseClasses.Equation.ascii[index]),
                if index == 0:
                    self._HTML += pythonequations.EquationBaseClasses.Equation.ascii[index]
                else:
                    self._HTML += pythonequations.EquationBaseClasses.Equation.ascii[index] + 'x<SUP>' + str(i) + '</SUP>y<SUP>' + str(j) + '</SUP>'
                if (i+1)*(j+1) != indexmax:
                    self._HTML += ' + '
                    
        pythonequations.EquationBaseClasses.Equation3D.Initialize(self)
